const { WebSocketServer } = require('ws');
const url = require('url');
const jwt = require('jsonwebtoken');
const moment = require('moment');
class ChatWebsocket {
    constructor() {
        this.wss = new WebSocketServer({ noServer: true });
        this.interval = null
        this.init();
    }
    init() {
        this.wss.on('connection', (ws, request) => {
            const { rawHeaders } = request;
            if (!this.isHaveToken(rawHeaders)) {
                ws.terminate();// 断开连接
                return;
            }
            const token = this.getToken(rawHeaders);

            const data = this.parseToken(token);
            if (!data) {
                console.log('token无法解析');
                ws.send(JSON.stringify({
                    type: 'error',
                    message: 'token无法解析'
                }))
                ws.terminate();// 断开连接
                return;
            }
            const { name, exp } = data
            ws.isAlive = true;
            ws.exp = exp;
            ws.nickName = name;
            this.send({
                type: 'system',
                time: moment().format('YYYY-MM-DD HH:mm:ss'),
                message: `${name}加入了聊天室`
            })
            ws.on('pong', function () {
                this.isAlive = true
            });
            ws.on('message', (message) => {
                this.send({
                    type: 'message',
                    nickName: ws.nickName,
                    time: moment().format('YYYY-MM-DD HH:mm:ss'),
                    message: message.toString(),
                });
            });
        })

        this.interval = setInterval(() => {
            this.wss.clients.forEach(function (ws) {
                if (ws.isAlive === false) {
                    return ws.terminate();
                }
                ws.isAlive = false;
                ws.ping();
            });
        }, 3000);

        this.wss.on('close', function close() {
            clearInterval(interval);
        });
    }
    send(message) {
        this.wss.clients.forEach((client) => {
            client.send(JSON.stringify(message));
        })
    }
    upgrade(request, socket, head) {
        const { pathname } = url.parse(request.url);
        if (pathname === '/chat') {
            this.wss.handleUpgrade(request, socket, head, (ws) => {
                this.wss.emit('connection', ws, request);
            });
        } else {
            socket.destroy();
        }
    }
    isHaveToken(rawHeaders) {
        if (!rawHeaders.includes('Cookie')) {
            return false;
        }
        return true;
    }
    getToken(rawHeaders) {
        const cookieIndex = rawHeaders.findIndex(item => item.includes('Cookie'));
        const token = rawHeaders[cookieIndex + 1]
        return token.split('=')[1];
    }
    parseToken(token) {
        try {
            return jwt.verify(token, '9527');
        } catch (e) {
            // console.log(e);
            return null;
        }
    }
}
module.exports = new ChatWebsocket();